Skip to content

Macos libs - #3948

Closed
mohamedtr wants to merge 3 commits into
boykopovar:mainfrom
mohamedtr:macos-libs
Closed

mohamedtr wants to merge 3 commits into
boykopovar:mainfrom
mohamedtr:macos-libs

Conversation

@mohamedtr

Copy link
Copy Markdown

What

Tested

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on:
  • AI-assisted:

Mohamed Trabelsi added 3 commits October 11, 2026 16:57
The relinker already produced macOS executables, but nothing built the
system libraries they load, so no title could start. This ports the
library tree to Darwin: all 122 build as x86-64 Mach-O dylibs and
dlopen cleanly, and a relinked title now reaches its first unresolved
import.

The bulk is glibc APIs that have no macOS spelling: <link.h>, mremap,
/proc/self/maps, getdents64, stat::st_mtim, pthread_getattr_np,
ppoll, RUSAGE_THREAD, memfd_create and others. ElfTypes.hpp carries the
ELF-shaped declarations Darwin needs and defers to <link.h> elsewhere,
so the other platforms are untouched.

Three areas needed more than a substitution:

  - The guest arena seeds itself from procfs and reserves gaps with
    MAP_FIXED_NOREPLACE. Neither exists on Darwin and mach_vm_region
    faults under Rosetta, so the macOS path probes with hinted mmap and
    keeps only the chunks the kernel placed exactly.

  - Inline assembly fails at link time here, not compile time. Mach-O
    has no .type or .size directive, calls need no @plt, and symbols
    written in asm need the leading underscore the C compiler adds.
    AsmMacros.hpp now covers all three formats, and APS5_EXPORT emits a
    tail jump instead of the ELF-only .set alias.

  - libc++ lacks std::atomic<std::shared_ptr<T>> and wants a non-const
    atomic_ref, so AtomicSharedPtr.hpp provides a mutex-backed drop-in.

__stack_chk_guard needed both a default visibility attribute to be
exported from libc.prx and a carve-out in the NID patcher: it is a
compiler ABI symbol, and renaming it broke the reference every other
library had already recorded against libc.prx.

Two build files also needed forwarding: libjpeg-turbo did not inherit
CMAKE_OSX_ARCHITECTURES, and $ORIGIN is an AnyPS5 loader convention that
dyld cannot resolve.
import_audit.py read ELF and PE only, so it refused every library the
macOS build produces. Mach-O exports live in an export trie rather
than a symbol table, so this walks the trie from LC_DYLD_INFO(_ONLY)
or LC_DYLD_EXPORTS_TRIE, skips weak definitions the way the ELF reader
does, and strips the leading underscore dyld hides and shows again on
lookup.

Running it on PPSA34356 turned up two absent imports, and they turned
out to be __stack_chk_fail and __stack_chk_guard: compiler symbols the
game imports by NID like any other. Adding them to a list kept verbatim
was wrong, because the guest resolves the NID name and nothing
exported it. Letting them be renamed to _f7uOxY9mM1U and _Ou3iL1abvng
fixes the guest side but leaves libkernel.prx holding a reference to a
name libc.prx no longer exports, because PatchChainedImports only
rewrites imports that look guest-facing -- an NID postfix or an sce
prefix, neither of which a compiler symbol has. Widening that filter to
the stack-protector names lets the existing rewrite follow the rename,
so both sides agree and every import in the title resolves.

The export trie reader has tests built around a real trie: a flat root
with one terminal child per name, weak definitions, and the bounds
checks.
The relinker's Mach-O writer gives every relinked image a TLS descriptor
and rewrites each %fs access into a call-out that reads %fs:0, which on
Darwin is pthread_self()->tsd, allocating through
Aps5GuestTlsAllocate when it is null. It also binds
Aps5GuestTlsRegister from the module init stub and
Aps5GuestTlsGetAddr with an addend for a guest that imports
__tls_get_addr. None of the three existed, so any title with a PT_TLS
segment stopped at dyld with "symbol not found in flat namespace".

Aps5GuestTlsAllocate sizes the block from the descriptor, copies the
init image, writes the guest thread pointer into the 16 bytes in front
of the block so a %fs:-16 access reaches it, and publishes the block
through host pthread key 0, which is free because the guest's own
pthread keys are emulated in separate storage. Aps5GuestTlsGetAddr is
the block itself as a thread-local variable, since the relinker binds
its address and adds the guest's offset to it.

The variable needs an asm label: this toolchain emits a Mach-O __thread
variable only outside an extern "C" block, and the default visibility
because the build compiles with -fvisibility=hidden.

Verified against the relinker's own TLS fixture and PPSA34356, both of
which now clear the TLS binds and stop on Aps5StartGuest instead.
@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
#3891 sceKernelGetdents
sceKernelGetdirentries

@github-actions github-actions Bot added libc libkernel build prx agc libSceAgc* needs rebase Conflicts with main, rebase needed labels Oct 11, 2026
@TideOPL

TideOPL commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Thanks for working on macOS. As submitted, this is hard to review:

  • Conventions check: it fails with an empty What/Tested, every checklist item unchecked, a non-Conventional title, 138 comment findings and 2 __attribute__ findings.
  • Size: about 2000 lines over 45 files, covering three topics (building the PRX libraries on macOS, the Mach-O import audit plus the stack-protector rename, and the guest TLS helpers). One PR per topic, each with a description and what was tested, would make it reviewable.
  • Structure: it adds 46 __APPLE__ branches across libkernel and libc. It may be worth agreeing with the maintainers on a layout (for example a specifics/macos/ layer like the existing specifics/linux and gcc ones) before splitting.

AI-assisted: yes. Written with AI assistance (Claude Code); I reviewed it.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Closing: the description is empty, Conventions fails (title, checklist, 138 comments), and the three commits are three topics over 45 files that conflict with main. Please reopen as one PR per topic with What and Tested filled in; the library build overlaps the macOS part of #3891, so check against it first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* build libc libkernel needs rebase Conflicts with main, rebase needed prx

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants